package dai.android.util

import android.app.Activity
import android.app.ActivityManager
import android.app.Application
import android.app.Service
import android.content.Context
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.os.Debug
import android.view.View
import androidx.core.app.NotificationManagerCompat
import com.helloandroid.tools.MyLog
import java.lang.Exception
import java.lang.StringBuilder
import java.lang.reflect.Method

// android 工具箱
object AndroidUtils {

    // 通知是否开启
    // ctx 可以为 applicationContext
    fun isNotificationEnabled(ctx: Context): Boolean = NotificationManagerCompat.from(ctx).areNotificationsEnabled()

    fun getAppVersionName(context: Context): String {
        val info = context.packageManager.getPackageInfo(context.packageName, 0)
        MyLog.info("getAppVersionName:${info.versionName}")
        return info.versionName
    }

    // 判断 app 是否在前台
    fun isAppInFg(context: Context): Boolean {
        val activityMgr = context.getSystemService(Service.ACTIVITY_SERVICE) as ActivityManager
        val appProcesses = activityMgr.runningAppProcesses
        for (process in appProcesses) {
            if (process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
                    process.processName == context.packageName) {
                return true
            }
        }
        return false
    }

    // 反射去拿进程名
    fun getCurrentProcessNameByAT(): String? {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            return Application.getProcessName()
        }

        var processName: String? = null
        try {
            val declaredMethod: Method = Class.forName("android.app.ActivityThread", false, Application::class.java.classLoader)
                    .getDeclaredMethod("currentProcessName")
            declaredMethod.isAccessible = true
            val invoke = declaredMethod.invoke(null)
            if (invoke is String) {
                processName = invoke
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        }
        return processName
    }

    // 通过ActivityManager获取到进程名字
    fun getCurrentProcessName(context:Context):String?{

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            return Application.getProcessName()
        }

        var myPid = android.os.Process.myPid()
        var activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        var runningAppProcesses = activityManager.runningAppProcesses
        if (!runningAppProcesses.isNullOrEmpty()){
            runningAppProcesses.forEach {
                if (it.pid == myPid){
                    return it.processName
                }
            }
        }
        return null
    }

    // 显示内存情况,用于调试
    fun showMem(activity: Activity){
        val am = activity.getSystemService(Activity.ACTIVITY_SERVICE) as ActivityManager
        val memInfo = ActivityManager.MemoryInfo()
        am.getMemoryInfo(memInfo)

        MyLog.info("===================================================")
        MyLog.info("可用内存:${memInfo.availMem / 1024 / 1024} M")
        MyLog.info("is low memory: ${memInfo.lowMemory}")
        MyLog.info("getNativeHeapAllocatedSize mem:${Debug.getNativeHeapAllocatedSize() / 1024 / 1024} M")
        MyLog.info("getNativeHeapFreeSize mem:${Debug.getNativeHeapFreeSize() / 1024 / 1024} M")
        MyLog.info("getNativeHeapSize mem:${Debug.getNativeHeapSize() / 1024 / 1024} M")
        MyLog.info("===================================================")
    }

    /**
     * 测量 view 的宽高
     */
    @JvmStatic
    fun measureViewSize(view: View):Pair<Int, Int>{
        val w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
        val h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
        view.measure(w, h)
        val height: Int = view.measuredHeight
        val width: Int = view.measuredWidth
        return width to height
    }

    // 获取手机信息,用于适配调试
    fun getPhoneInfo(context: Context): String {
        val dm = context.resources.displayMetrics
        val width = dm.widthPixels
        val height = dm.heightPixels
        val density = dm.density // 屏幕密度

        // 屏幕宽度 单位为 dp
        val screenWidth = (width / density).toInt() //
        val screenHeight = (height / density).toInt()
        val sb = StringBuilder()
        sb.append("屏幕像素:${width}x${height}\n")
        sb.append("屏幕密度:${density}\n")
        sb.append("屏幕dp:${screenWidth}dpX${screenHeight}dp\n")
        sb.append("scaledDensity:${dm.scaledDensity}\n")
        try {
            val pm = context.packageManager
            val info = pm.getPackageInfo(context.packageName, PackageManager.GET_ACTIVITIES)
            sb.append("应用版本名:${info.versionName}\n")
            sb.append("Android:${Build.VERSION.RELEASE}, Build_Sdk:${Build.VERSION.SDK_INT}\n")
            sb.append("${Build.MODEL},品牌:${Build.BRAND}\n")
        } catch (exp: PackageManager.NameNotFoundException) {
            sb.append("pm.getPackageInfo() error!\n")
        }
        return sb.toString()
    }

    // 是否连接网络
    fun networkConnected(appContext:Context): Boolean {
        val cm = appContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val network = cm.activeNetwork
        if (network != null) {
            val nc = cm.getNetworkCapabilities(network)
            if (nc != null) {
                if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { //WIFI
                    return true
                } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { //移动数据
                    return true
                }
            }
        }
        return false
    }

    //  计算状态栏高度
    fun getStateBarHeight(ctx:Context):Int{
        return try {
            val resourceId: Int = ctx.resources.getIdentifier("status_bar_height", "dimen", "android")
            ctx.resources.getDimensionPixelSize(resourceId)
        }catch (e:Exception){
            MyLog.info("获取状态栏高度失败!")
            0
        }
    }
}